package com.gzyz.cheetah.interceptor;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.gzyz.cheetah.annotations.AdminJwtIntercept;
import com.gzyz.cheetah.entity.table.Admin;
import com.gzyz.cheetah.exception.AbstractServiceException;
import com.gzyz.cheetah.exception.AdminServiceException;
import com.gzyz.cheetah.util.RedisUtil;
import com.gzyz.cheetah.util.ThreadLocalUtil;
import com.gzyz.cheetah.util.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author xclhove
 */
@Slf4j
public class AdminJwtInterceptor extends AbstractInterceptor {
    @Resource
    private RedisUtil redis;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        try {
            //如果不是映射到方法直接通过
            if (!(handler instanceof HandlerMethod)) {
                return true;
            }
            
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            AdminJwtIntercept loginIntercept = handlerMethod.getMethod().getAnnotation(AdminJwtIntercept.class);
            //如果要访问的方法上没有加这个注解，那么就说明这个方法不需要拦截，否则就需要进行拦截
            if(null == loginIntercept) {
                return true;
            }
            
            String token = request.getHeader("Authorization");
            if (StrUtil.isBlank(token)) {
                throw new AdminServiceException("未登录！");
            }
            Integer id = TokenUtil.getId(token);
            
            //将token与redis中的token对比
            String tokenInRedis = redis.getHashString("admin_token", id);
            if (!tokenInRedis.equals(token)) {
                throw new AdminServiceException("token无效！");
            }
            
            Admin admin = Db.getById(id, Admin.class);
            //校验token
            if (!TokenUtil.validate(token, admin.getPassword())) {
                throw new AdminServiceException("token校验未通过！");
            }
            //将id存入ThreadLocal
            ThreadLocalUtil.set("id", id);
            return true;
        } catch (AbstractServiceException serviceException) {
            log.error(serviceException.getMessage());
            throw serviceException;
        }
        catch (Exception e) {
            log.error(e.toString());
            throw new AdminServiceException("token校验异常！");
        }
    }
}